﻿using KPIS.GERP.Models;
using KPIS.GERP.Models.Class;
using KPIS.GERP.Models.ICM;
using KPIS.GERP.Models.ICM.ViewModel;
using KPIS.GERP.Models.SYS;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.ServiceModel;
using System.Web.Mvc;

namespace KPIS.GERP.WCF.GIMS
{
    [ServiceContract]
    public interface IMovementService
    {
        [OperationContract]
        IEnumerable<KPIS.GERP.Models.ICM.Movement> Select(Movement criteriaModel = null, List<string> includeSubObjectString = null);

        [OperationContract]
        int Insert(Movement m, int createByUserId);

        [OperationContract]
        void Update(Movement model, int updateByUserId);

        [OperationContract]
        void Delete(int id, int deleteByUserId);

        [OperationContract]
        IEnumerable<KPIS.GERP.Models.ICM.MovementDtl> SelectMovementDtl(MovementDtl criteriaModel = null,
                                                                        List<string> includeSubObjectString = null);

        [OperationContract]
        int InsertMovementDtl(MovementDtl model, int createByUserId);

        [OperationContract]
        void UpdateMovementDtl(MovementDtl model, int updateByUserId);

        [OperationContract]
        void DeleteMovementDtl(int id, int deleteByUserId);

        [OperationContract]
        IList<SelectListItem> SelectListMovement(Movement criteriaModel = null);

        [OperationContract]
        IEnumerable<KPIS.GERP.Models.ICM.MovementHistory> SelectMovementHistory(MovementHistory criteriaModel = null, List<string> includeSubObjectString = null);

        [OperationContract]
        int InsertMovementHistory(MovementHistory model, int createByUserId);

        [OperationContract]
        void DeleteMovementHistory(int id, int deleteByUserId);

        [OperationContract]
        List<Dictionary<string, string>> MovementReportDtls(int MovementId);

        [OperationContract]
        string[] MovementReportHead(int MovementId);

    }

    #region Movement
    [ServiceErrorBehavior(typeof(ElmahErrorHandler))]
    public class MovementService : IMovementService
    {
        public IEnumerable<KPIS.GERP.Models.ICM.Movement> Select(Movement criteriaModel = null, List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<Movement> query = context.Movements;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query, (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    return query.ToList();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int Insert(Movement m, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    if (m.MoveMethod == 1)
                    {
                        m.RecordStatus = RecordStatus.UsedStatus;
                        m.CreatedBy = createByUserId;
                        m.CreatedWhen = DateTime.Now;
                        m.SourceJobSiteId = null;
                        context.Movements.Add(m);
                        context.SaveChanges();
                    }
                    else if (m.MoveMethod == 2)
                    {
                        m.RecordStatus = RecordStatus.UsedStatus;
                        m.CreatedBy = createByUserId;
                        m.CreatedWhen = DateTime.Now;
                        m.SourceWarehouseId = null;
                        context.Movements.Add(m);
                        context.SaveChanges();
                    }
                    
                    return m.MovementId;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Update(Movement model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Delete(int id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.Movements.Find(id);
                    if (modelToDelete == null) return;

                    context.Entry(modelToDelete).State = EntityState.Modified;
                    modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    modelToDelete.UpdatedBy = deleteByUserId;
                    modelToDelete.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    #endregion


        #region MovementDtl

        public IEnumerable<KPIS.GERP.Models.ICM.MovementDtl> SelectMovementDtl(MovementDtl criteriaModel = null, List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<MovementDtl> query = context.MovementDtls;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query, (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    return query.ToList();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int InsertMovementDtl(MovementDtl model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var existData = context.MovementDtls
                       .Where(m => m.AssetId == model.AssetId
                        && m.MovementId == model.MovementId
                        && m.RecordStatus != RecordStatus.DeletedStatus).ToList();

                    if (existData.Count == 0)
                    {
                        model.RecordStatus = RecordStatus.UsedStatus;
                        model.CreatedBy = createByUserId;
                        model.CreatedWhen = DateTime.Now;
                        context.MovementDtls.Add(model);
                        context.SaveChanges();
                        return model.MovementDtlId;
                    }
                    else
                    {
                        throw new Exception("เกิดข้อผิดพลาด!! ข้อมูลนี้มีบันทึกอยู่แล้ว");
                    }

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void UpdateMovementDtl(MovementDtl model, int updateByUserId)
        {
            //try
            //{
            using (var context = new GERPContext())
            {
                //var existData = context.MovementDtls
                //    .Where(m => m.RecordStatus != RecordStatus.DeletedStatus).ToList();

                //if (existData.Count == 0)
                //{
                context.Entry(model).State = EntityState.Modified;
                model.UpdatedBy = updateByUserId;
                model.UpdatedWhen = DateTime.Now;
                context.SaveChanges();
            }
            //        else
            //        {
            //            throw new Exception("เกิดข้อผิดพลาด!! ข้อมูลนี้มีบันทึกอยู่แล้ว");
            //        }
            //    }
            //}
            //catch (Exception ex)
            //{
            //    throw ex;
            //}
        }

        public void DeleteMovementDtl(int id, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.MovementDtls.Find(id);
                    if (modelToDelete == null) return;

                    context.Entry(modelToDelete).State = EntityState.Modified;
                    modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    modelToDelete.UpdatedBy = deleteByUserId;
                    modelToDelete.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IList<SelectListItem> SelectListMovement(Movement criteriaModel = null)
        {
            var list = new List<SelectListItem>();

            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<Movement> query = context.Movements;

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    var x = query.ToList();
                    foreach (var model in x)
                    {
                        var item = new SelectListItem { Text = model.Title, Value = model.MovementId.ToString() };
                        list.Add(item);
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return list;
        }

        #endregion

        #region MovementHistory

        public IEnumerable<KPIS.GERP.Models.ICM.MovementHistory> SelectMovementHistory(MovementHistory criteriaModel = null, List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<MovementHistory> query = context.MovementHistorys;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query, (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    return query.ToList();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public int InsertMovementHistory(MovementHistory model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    model.RecordStatus = RecordStatus.UsedStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    context.MovementHistorys.Add(model);
                    context.SaveChanges();
                    return model.MoveHistId;

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void DeleteMovementHistory(int refno, int deleteByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    var modelToDelete = context.MovementHistorys.Find(refno);
                    if (modelToDelete == null) return;

                    context.Entry(modelToDelete).State = EntityState.Modified;
                    modelToDelete.RecordStatus = RecordStatus.DeletedStatus;
                    modelToDelete.UpdatedBy = deleteByUserId;
                    modelToDelete.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #endregion

        #region MovementHistory

        public List<Dictionary<string, string>> MovementReportDtls(int MovementId)
        {
            GERPContext context = new GERPContext();

            var x = (from a in context.Movements
                     join b in context.MovementDtls on a.MovementId equals b.MovementId
                     join c in context.Assets on b.AssetId equals c.AssetId
                     where a.MovementId == MovementId
                     select new { c.AssetName, c.AssetCode }).ToList();

            List<Dictionary<string, string>> Dics = new List<Dictionary<string, string>>();
            int nIndex = 1;
            foreach (var item in x)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();

                dic.Add("No", nIndex.ToString());
                dic.Add("AssetName", item.AssetName);
                dic.Add("AssetCode", item.AssetCode);

                Dics.Add(dic);
                nIndex++;
            }

            return Dics;

        }

        public string[] MovementReportHead(int MovementId)
        {
            string EmpName = "";
            string PosName = "";
            string JobSiteName = "";
            string SubJobSiteName = "";
            string RefNo = "";

            using (var context = new GERPContext(false))
            {
                var x = (from a in context.Movements
                         join b in context.Employees on a.CreatedBy equals b.EmpId into bs
                         from b in bs.DefaultIfEmpty()
                         join c in context.Positions on b.PosId equals c.PosId into cs 
                         from c in cs.DefaultIfEmpty()
                         join d in context.JobSites on b.WorkingJobSiteId equals d.JobSiteId into ds
                         from d in ds.DefaultIfEmpty()
                         join e in context.JobSites on d.UpperJobSiteId equals e.JobSiteId into es
                         from e in es.DefaultIfEmpty()
                         join h in context.JobSites on e.UpperJobSiteId equals h.JobSiteId into hs
                         from h in hs.DefaultIfEmpty()
                         where a.MovementId == MovementId
                         select new { EmpName = (b.FirstName + "  " + b.LastName), PosName = c.Name, JobSiteName = d.Name, UpperJobSiteName = e.Name, d.JobSiteLevelId
                         , UpperJobSiteName2 = h.Name, a.RefNo}).FirstOrDefault();
                if (x != null)
                {
                    EmpName = x.EmpName;
                    PosName = x.PosName;
                    if (x.JobSiteLevelId == 3 || x.JobSiteLevelId == 2)
                    {
                        JobSiteName = x.JobSiteName;
                        SubJobSiteName = "";
                    }
                    else if(x.JobSiteLevelId == 4)
                    {
                        SubJobSiteName = x.JobSiteName;
                        JobSiteName = x.UpperJobSiteName;
                    }
                    else if (x.JobSiteLevelId == 5)
                    {
                        SubJobSiteName = x.UpperJobSiteName;
                        JobSiteName = x.UpperJobSiteName2;
                    }
                    RefNo = x.RefNo;
                }
            }
            return new string[] { EmpName, PosName, JobSiteName, SubJobSiteName, RefNo };
        }
    

        #endregion

    }
    
}

